/**
 * @file factory_mode_hwtest.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_FACTORYMODE_HWTEST != 0

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static lv_engineer_hwtest_obj_ext_t * hwtest_get_ext(void);
static lv_obj_t * hwtest_list_add(lv_obj_t * list, const char * str, lv_event_cb_t rel_event_cb);
static void hwtest_list_btn_rel_event_cb(lv_obj_t * btn, lv_event_t e);
static void hwtest_bottm_btn_create(lv_obj_t * par);
static void hwtest_sel_btn_rel_event_cb(lv_obj_t * btn, lv_event_t e);
static void hwtest_test_btn_rel_event_cb(lv_obj_t * btn, lv_event_t e);
static void hwtest_start_test(void);
static void hwtest_stop_test(void);
static void hwtest_emmc_task(lv_task_t * task);
static void hwtest_camera_preview_task(lv_task_t * task);
static void hwtest_cpu_overload_task(lv_task_t * task);
static void hwtest_prepare_destory(lv_obj_t * activity_obj);

/**********************
 *  STATIC VARIABLES
 **********************/
LV_AUDIO_DECLARE(audio_incoming_call);

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
***********************/
lv_obj_t * factorymode_hwtest_create(lv_obj_t * activity_obj)
{
    const watchLangTxtId_t hwtest_list[] = {
        WATCH_TEXT_ID_EMMC_ERASE,
        WATCH_TEXT_ID_LCD_BRIGHTEST_SLEEPLESS,
        WATCH_TEXT_ID_START_VIBRATION,
        WATCH_TEXT_ID_OPEN_CAMERA,
        WATCH_TEXT_ID_PLAY_MUSIC,
        WATCH_TEXT_ID_GPS,
        WATCH_TEXT_ID_TR_WIFI,
        WATCH_TEXT_ID_CPU_OVERLOAD,
        WATCH_TEXT_ID_GSENSOR,
    };

    lv_obj_t * obj;
    if(activity_obj == NULL) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_FACTORY_MODE_PERFM_TEST;
        activity_ext.create = factorymode_hwtest_create;
        activity_ext.prepare_destory = hwtest_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
        LV_ASSERT_MEM(activity_obj);
        if(NULL == activity_obj) {
            return NULL;
        }
    }

    obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    if(NULL == obj) {
        return NULL;
    }

    lv_engineer_hwtest_obj_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_engineer_hwtest_obj_ext_t));
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return NULL;

    ext->select_all = false;
    ext->test_started = false;
    for(uint8_t i = 0; i < HWTEST_LIST_CNT; i++) {
        ext->hwtest_sel[i] = false;
    }

    //title
    lv_obj_t * title = lv_label_create(obj, NULL);
    lv_obj_set_size(title, LV_HOR_RES, LV_VER_RES / 6);
    lv_label_set_text_id(title, WATCH_TEXT_ID_PERFORMANCE_TEST);
    lv_obj_add_style(title, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_obj_align(title, NULL, LV_ALIGN_IN_TOP_MID, 0, 5);

    //list
    lv_obj_t * list = lv_list_create(obj, NULL);
    lv_obj_set_size(list, LV_HOR_RES, LV_VER_RES - lv_obj_get_height(title) - 55);
    lv_page_set_edge_flash(list, true);
    lv_obj_add_style(list, LV_PAGE_PART_BG, &lv_watch_style_transp);
    lv_obj_add_style(list, LV_PAGE_PART_SCROLLABLE, &lv_watch_style_transp);
    lv_obj_add_style(list, LV_PAGE_PART_EDGE_FLASH, &lv_watch_cont_opa1);
    lv_obj_align(list, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    uint8_t i = 0;
    lv_obj_t * btn;
    for(i = 0; i < HWTEST_LIST_CNT; i++) {
        btn = hwtest_list_add(list, lv_lang_get_text(hwtest_list[i]), hwtest_list_btn_rel_event_cb);
        lv_watch_set_free_num(btn, i);
        ext->list_btn[i] = btn;
    }

    //bottom button
    hwtest_bottm_btn_create(obj);

    return obj;
}

/**********************
 *   STATIC FUNCTIONS
 **********************/
static lv_engineer_hwtest_obj_ext_t * hwtest_get_ext(void)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_FACTORY_MODE_PERFM_TEST);
    if(activity_obj == NULL) return NULL;

    lv_obj_t * watch_obj;
    lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj);
    if(watch_obj == NULL) return NULL;

    if(watch_obj) {
        lv_engineer_hwtest_obj_ext_t * ext = lv_obj_get_ext_attr(watch_obj);
        return ext;
    }
    return NULL;
}

static lv_obj_t * hwtest_list_add(lv_obj_t * list, const char * str, lv_event_cb_t rel_event_cb)
{
    /*Create a list element with the image an the text*/
    lv_obj_t * btn = lv_btn_create(list, NULL);

    /*Save the original signal function because it will be required in `lv_list_btn_signal`*/
    lv_list_set_ancestor_btn_signal(btn);

    /*Set the default styles*/
    lv_obj_add_style(btn, LV_BTN_PART_MAIN,  &lv_watch_style_transp);

    lv_obj_set_event_cb(btn, rel_event_cb);
    lv_page_glue_obj(btn, true);
    lv_btn_set_layout(btn, LV_LAYOUT_ROW_MID);
    lv_obj_add_protect(btn, LV_PROTECT_PRESS_LOST);
    lv_obj_set_signal_cb(btn, lv_list_get_listbtn_signal());

    /*Make the size adjustment*/
    lv_coord_t w = lv_obj_get_width(list);
    uint8_t pad_w = w - 16;
    lv_obj_set_size(btn, pad_w, 30);
    lv_obj_set_x(btn, 8);
    lv_watch_obj_add_element(btn);

    lv_obj_t * img = lv_img_create(btn, NULL);
    lv_img_set_src(img, ICON_UNCHECK);
    lv_obj_align(img, btn, LV_ALIGN_IN_LEFT_MID, 5, 0);
    lv_watch_obj_add_element(img);

    lv_obj_t * label = lv_label_create(btn, NULL);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_label_set_long_mode(label, LV_LABEL_LONG_SROLL);
    lv_obj_set_width(label, pad_w - lv_obj_get_width(img) - 20);
    lv_label_set_text(label, str);
    lv_obj_align(label, img, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
    lv_watch_obj_add_element(label);

    return btn;
}

static void hwtest_list_btn_rel_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e)
    {
        lv_engineer_hwtest_obj_ext_t * ext = hwtest_get_ext();
        lv_obj_t * img = lv_obj_get_child_back(btn, NULL);
        uint32_t num = lv_obj_get_user_data(btn).user_num;

        if(true == ext->hwtest_sel[num]) {
            ext->hwtest_sel[num] = false;
            lv_img_set_src(img, ICON_UNCHECK);
        } else {
            ext->hwtest_sel[num] = true;
            lv_img_set_src(img, ICON_CHECK_TEST);
        }
    }
}

static void hwtest_bottm_btn_create(lv_obj_t * par)
{
    lv_engineer_hwtest_obj_ext_t * ext = hwtest_get_ext();

    lv_obj_t * sel_btn = lv_btn_create(par, NULL);
    lv_obj_t * sel_label = lv_label_create(sel_btn, NULL);
    lv_obj_set_size(sel_btn, LV_HOR_RES / 2, LV_VER_RES / 7);
    lv_label_set_text_id(sel_label, WATCH_TEXT_ID_SELECT_ALL);
    lv_obj_set_event_cb(sel_btn, hwtest_sel_btn_rel_event_cb);
    lv_obj_align(sel_btn, par, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
    lv_obj_add_style(sel_label, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_obj_add_protect(sel_btn, LV_PROTECT_PRESS_LOST);
    lv_watch_obj_add_element(sel_btn);
    ext->sel_btn = sel_btn;

    lv_obj_t * test_btn = lv_btn_create(par, NULL);
    lv_obj_t * test_label = lv_label_create(test_btn, NULL);
    lv_obj_set_size(test_btn, LV_HOR_RES / 2, LV_VER_RES / 7);
    lv_label_set_text_id(test_label, WATCH_TEXT_ID_START_TEST);
    lv_obj_set_event_cb(test_btn, hwtest_test_btn_rel_event_cb);
    lv_obj_align(test_btn, sel_btn, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
    lv_obj_add_style(test_label, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_obj_add_protect(test_btn, LV_PROTECT_PRESS_LOST);
    lv_watch_obj_add_element(test_btn);
    ext->test_btn = test_btn;
}

static void  hwtest_sel_btn_rel_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e)
    {
        lv_obj_t * label;
        lv_obj_t * img;
        lv_engineer_hwtest_obj_ext_t * ext = hwtest_get_ext();

        if(false == ext->select_all) {   //select all
            for(uint8_t i = 0; i < HWTEST_LIST_CNT; i++) {
                ext->hwtest_sel[i] = true;
                img = lv_obj_get_child_back(ext->list_btn[i], NULL);
                lv_img_set_src(img, ICON_CHECK_TEST);

                label = lv_obj_get_child_back(btn, NULL);
                lv_label_set_text_id(label, WATCH_TEXT_ID_SELECT_NONE);
            }
        } else {    //select none
            for(uint8_t i = 0; i < HWTEST_LIST_CNT; i++) {
                ext->hwtest_sel[i] = false;
                img = lv_obj_get_child_back(ext->list_btn[i], NULL);
                lv_img_set_src(img, ICON_UNCHECK);

                label = lv_obj_get_child_back(btn, NULL);
                lv_label_set_text_id(label, WATCH_TEXT_ID_SELECT_ALL);
            }
        }

        ext->select_all = !ext->select_all;
    }
}

static void hwtest_test_btn_rel_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e)
    {
        lv_obj_t * label;
        lv_engineer_hwtest_obj_ext_t * ext = hwtest_get_ext();
        uint8_t i = 0;

        if(false == ext->test_started) {   //start test
            for(i = 0; i < HWTEST_LIST_CNT; i++) {
                if(true == ext->hwtest_sel[i]) {
                    break;
                }
            }
            if(HWTEST_LIST_CNT == i) {
                return;
            }

            label = lv_obj_get_child_back(btn, NULL);
            lv_label_set_text_id(label, WATCH_TEXT_ID_STOP_TEST);

            for(i = 0; i < HWTEST_LIST_CNT; i++) {
                lv_obj_set_click(ext->list_btn[i], false);
            }
            lv_obj_set_click(ext->sel_btn, false);

            //start test
            hwtest_start_test();
        } else {    //stop test
            label = lv_obj_get_child_back(btn, NULL);
            lv_label_set_text_id(label, WATCH_TEXT_ID_START_TEST);

            for(i = 0; i < HWTEST_LIST_CNT; i++) {
                lv_obj_set_click(ext->list_btn[i], true);
            }
            lv_obj_set_click(ext->sel_btn, true);

            //stop test
            hwtest_stop_test();
        }

        ext->test_started = !ext->test_started;
    }
}

static void hwtest_start_test(void)
{
    lv_engineer_hwtest_obj_ext_t * ext = hwtest_get_ext();
    uint8_t i = 0;

    if(ext->hwtest_sel[i++]) {  //EMMC erase
        ext->emmc_task = lv_task_create(hwtest_emmc_task, 100, LV_TASK_PRIO_HIGH, NULL);
    }

    if(ext->hwtest_sel[i++]) {  //LCD brightest and sleepless
        Hal_Backlight_Intensity_Set(HAL_INTENSITY_LEVEL_5);
    }

    if(ext->hwtest_sel[i++]) {  //Start vibration
        Hal_Vibrator_Play_Repeat();
    }

    if(ext->hwtest_sel[i++]) {  //Open camera
        lv_obj_t * cont = lv_cont_create(lv_obj_get_parent(ext->test_btn), NULL);
        lv_obj_set_size(cont, LV_HOR_RES, LV_VER_RES);
        lv_obj_add_style(cont, LV_CONT_PART_MAIN, &(lv_watch_black_tight));
        ext->cont_camera = cont;

        cam_start_preview_t cam_params;
        cam_params.width = 240;
        cam_params.height = 240;
        cam_params.sensor_id = 0;
        Hal_Camera_Start_Preview(&cam_params);

        ext->img_camera.header.always_zero = 0;
        ext->img_camera.header.w = lv_obj_get_width(lv_obj_get_parent(cont));
        ext->img_camera.header.h = lv_obj_get_height(lv_obj_get_parent(cont));
        ext->img_camera.data_size = ext->img_camera.header.w * ext->img_camera.header.h * LV_COLOR_SIZE / 8;
        ext->img_camera.header.cf = LV_IMG_CF_TRUE_COLOR;
        ext->img_camera.data = lv_mem_alloc(ext->img_camera.header.w * ext->img_camera.header.h * LV_COLOR_SIZE / 8);
        LV_ASSERT_MEM(ext->img_camera.data);
        if(ext->img_camera.data == NULL) return;
        memset((void *)ext->img_camera.data, 0, ext->img_camera.header.w * ext->img_camera.header.h * LV_COLOR_SIZE / 8);

        lv_obj_t * img = lv_img_create(cont, NULL);
        lv_img_cache_invalidate_src(&ext->img_camera);
        lv_img_set_src(img, &ext->img_camera);
        lv_obj_set_parent(ext->test_btn, img);

        ext->camera_preview_task = lv_task_create(hwtest_camera_preview_task, 100, LV_TASK_PRIO_HIGH, (void *)img);
    }

    if(ext->hwtest_sel[i++]) {  //Play music
        Hal_NFFS_File_Play_Onetime(AUDIO_INCOMING_CALL, query_current_volume(), NULL, NULL);
    }

    if(ext->hwtest_sel[i++]) {  //GPS
    }

    if(ext->hwtest_sel[i++]) {  //WIFI
    }

    if(ext->hwtest_sel[i++]) {  //CPU overload
        ext->cpu_overload_task = lv_task_create(hwtest_cpu_overload_task, 10, LV_TASK_PRIO_HIGH, NULL);
    }

    if(ext->hwtest_sel[i++]) {  //gsensor
    }
}

static void hwtest_stop_test(void)
{
    lv_engineer_hwtest_obj_ext_t * ext = hwtest_get_ext();
    uint8_t i = 0;

    if(ext->hwtest_sel[i++]) {  //EMMC erase
        lv_task_del(ext->emmc_task);
        ext->emmc_task = NULL;
    }

    if(ext->hwtest_sel[i++]) {  //LCD brightest and sleepless
        setting_set_backlight_intensity(setting_get_backlight_intensity(), true);
    }

    if(ext->hwtest_sel[i++]) {  //Start vibration
        Hal_Vibrator_Play_End();
    }

    if(ext->hwtest_sel[i++]) {  //Open camera
        Hal_Camera_Stop_Preview(0);

        lv_mem_free(ext->img_camera.data);
        ext->img_camera.data = NULL;
        lv_task_del(ext->camera_preview_task);
        ext->camera_preview_task = NULL;

        lv_obj_set_parent(ext->test_btn, lv_obj_get_parent(ext->sel_btn));
        lv_obj_del(ext->cont_camera);
    }

    if(ext->hwtest_sel[i++]) {  //Play music
        Hal_Tone_Play_End();
    }

    if(ext->hwtest_sel[i++]) {  //GPS
    }

    if(ext->hwtest_sel[i++]) {  //WIFI
    }

    if(ext->hwtest_sel[i++]) {  //CPU overload
        lv_task_del(ext->cpu_overload_task);
        ext->cpu_overload_task = NULL;
    }

    if(ext->hwtest_sel[i++]) {  //gsensor
    }
}

static void hwtest_emmc_task(lv_task_t * task)
{
}

static void hwtest_camera_preview_task(lv_task_t * task)
{
    lv_engineer_hwtest_obj_ext_t * ext = hwtest_get_ext();
    if(Hal_Camera_Preview((uint8_t *)ext->img_camera.data)) {
        //update the src of img.
        lv_obj_t * img = (lv_obj_t *)task->user_data;
        lv_img_set_src(img, &ext->img_camera);
    }
    lv_task_set_period(ext->camera_preview_task, 30);
}

static void hwtest_cpu_overload_task(lv_task_t * task)
{
    for(uint8_t i = 0; i < 5; i++) {
        printf("cpu overload test\n");
    }
}

static void hwtest_prepare_destory(lv_obj_t * activity_obj)
{
    lv_watch_png_cache_all_free();

    lv_engineer_hwtest_obj_ext_t * ext = hwtest_get_ext();
    if(ext->test_started) {
        hwtest_stop_test();
    }
}

#endif /*USE_LV_WATCH_FACTORY_MODE*/
